2022-08-23

Wardialing My Grandmother

Before we get to the technical things, I think I should first explain the little ritual my grandmother and I have developed over the years. I call her a few times a month and we usually talk for about an hour. However, neither of us likes setting a date for this, so our strategy is that I just call her when I have time. I can't call her mobile phone, because it is usually in silent mode. So instead I have to call her on the landline. Usually she does not pick up right away. What works best is ringing four or five times, hanging up and just waiting for her to reach the phone and call me back.

Now, I use a pre-paid SIM card, because I don't make enough calls for a contract to be worth it and because I also don't need mobile internet (every place I need to be has WiFi these days). Recently I ran out of money on the card, so could not call using my mobile phone.

Instead I had a fun idea: I have an old rotary-dial phone sitting on a shelf behind me and the router/phone-system hybrid boxes that are common here in Germany still support them, in theory. So I fetched the phone and plugged it in. It did not work. I am pretty sure the phone is functioning perfectly, so probably an issue with the box.

Then I remembered that these things allow you to dial the phone via the webinterface (the way old phones worked allows for the dialing device and the device used for the actual call to be different). It was a bit clunky, but worked. My grandmother calls me first when she does not recognize a number that called her, for legacy reasons. So me using my previously never touched landline connection was not a problem. We had a nice talk that day, as usual.

About a week later I thought that I should be able to automate this.

At first I tried to just mimic how user input would be over the webinterface with curl, using a helpful write-up. Unfortunately, I did not get past the initial login, likely because things have changed since that article was written. I am not proficient at reverse-engineering web-things, so this first attempt died here.

Then I found out that there was apparently a control interface / protocol (?) that can be used locally to control the box, called TR064. And there is a python package for it! Unfortunately I could figure out how to make that package emit the right web-call-thingy for dialing to work. Dialing is apparently a custom add-on by the manufacturer and not in the standard.

I did find a reference, inluding also the custom extensions. It did not help me with the python library, so I tried searching online for some of the interface names. When searching for "X_AVM-DE_DialNumber", I got lucky. Why can't things always be this nice?

I found an article that has an example of using the TR064 thing with curl and netcat! Using netcat apparently doesn't work anymore, likely because a lot of the interfaces got deprecated. But the curl example still works! Not very reliable, one out of three attempts fails.

Oh, and now apparently all attempts fail? What? Maybe I called myself a bit too often and some system somewhere decided it needs to block the number now? No, wait, I simply did not have reception at my desk. That is technically a bit weirder, but let's move on.

Anyway, when it fails to order an auto-dial, we actually get a response, telling us that it fails! It doesn't tell us why it fails, at least not to my knowledge, but who needs such information anyway, right? So my outrageously horrible script checks if we got the dreaded error response. If yes, try again. If no ...

To understand what needs to happen next, we need to understand how the auto-dialer is supposed to function. When you auto-dial a number, the box calls the number. If the line is picked up, the box then calls your phone locally. A bit rude if you ask me. Luckily it also works without a phone connected; I prefer my rotary phone on my shelf.

So what I want the box to do after dialing is hang up. The dialing process takes some time, so I experimented a bit until I found a delay between the dial and hangup orders that worked for my purpose.

#!/bin/bash
shopt -s lastpipe

USER="fritz0944"
PASS="hunter2"
DIAL="0123456789"

function dial
{
	curl -4 -k --anyauth -u "${USER}:${PASS}" \
		"http://fritz.box:49000/upnp/control/x_voip" \
		-H 'Content-Type: text/xml; charset="utf-8"' \
		-H 'SoapAction: urn:dslforum-org:service:X_VoIP:1#X_AVM-DE_DialNumber' \
		-d '<?xml version="1.0" encoding="utf-8"?>
	        <s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
	            <s:Body>
	               <u:X_AVM-DE_DialNumber xmlns:u="urn:dslforum-org:service:X_VoIP:1">
	                 <NewX_AVM-DE_PhoneNumber>'${DIAL}'</NewX_AVM-DE_PhoneNumber>
	               </u:X_AVM-DE_DialNumber>
	            </s:Body>
	        </s:Envelope>'
}

function hangup
{
	curl -4 -k --anyauth -u "${USER}:${PASS}" \
		"http://fritz.box:49000/upnp/control/x_voip" \
		-H 'Content-Type: text/xml; charset="utf-8"' \
		-H 'SoapAction: urn:dslforum-org:service:X_VoIP:1#X_AVM-DE_DialHangup' \
		-d '<?xml version="1.0" encoding="utf-8"?>
	        <s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
	            <s:Body>
	               <u:X_AVM-DE_DialHangup xmlns:u="urn:dslforum-org:service:X_VoIP:1">
	               </u:X_AVM-DE_DialHangup>
	            </s:Body>
	        </s:Envelope>'
}

echo "Dialing..."
while true
do
	dial | read RESPONSE
	[ -z "$(echo "${RESPONSE}" | grep -i error)" ] && break
	sleep 1
	echo "(again)"
done

sleep 13

echo "Hanging up..."
while true
do
	hangup | read RESPONSE
	[ -z "$(echo "${RESPONSE}" | grep -i error)" ] && break
	sleep 1
	echo "(again)"
done

So now I have a script I can execute whenever I want to call my grandmother, which automates the first few step of our usual calling ritual.

While this was certainly a fun hack, the real value here is learning of TR064 and how to curl it, opening up an entire world of stupid very sane and mentally healthy things to do.

Articles from blogs I read (generated by openring)

whippet lab notebook: guile, heuristics, and heap growth

Greets all! Another brief note today. I have gotten Guile working with one of the Nofl-based collectors, specifically the one that scans all edges conservatively (heap-conservative-mmc / heap-conservative-parallel-mmc). Hurrah!It was a pleasant surprise h…

wingolog, May 22, 2025

Status update, May 2025

Hi! Today wlroots 0.19.0 has finally been released! Among the newly supported protocols, color-management-v1 lays the first stone of HDR support (backend and renderer bits are still being reviewed) and ext-image-copy-capture-v1 enhances the previous screen ca…

emersion, May 15, 2025

Summary of changes for April 2025

Hey everyone!This is the list of all the changes we've done to our projects during the month of April. 100r.co, updated water, ditch bag, woodstove installation, and added new photos and information on first-aid kit. Rabbit Waves, updated Triangular…

Hundred Rabbits, April 30, 2025